home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / text / hyper / hsc_source.lha / hsc / source / hsclib / tag_macr.c < prev    next >
C/C++ Source or Header  |  1996-11-25  |  10KB  |  375 lines

  1. /*
  2.  * hsclib/tag_macr.c
  3.  *
  4.  * tag callbacks for "<$MACRO>" and "<macro>"
  5.  *
  6.  * Copyright (C) 1995,96  Thomas Aglassinger
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  * updated: 30-Oct-1996
  23.  * created:  5-Aug-1995
  24.  */
  25.  
  26. #include "hsclib/inc_tagcb.h"
  27.  
  28. #include "hsclib/defattr.h"
  29. #include "hsclib/deftag.h"
  30. #include "hsclib/include.h"
  31. #include "hsclib/parse.h"
  32.  
  33. /* TODO: skip hsc comments */
  34.  
  35. /* states for read_macro_text */
  36. #define MAST_TEXT   0           /* inside text      */
  37. #define MAST_LT     1           /* after "<"        */
  38. #define MAST_SLASH  2           /* after "</"       */
  39. #define MAST_CMACRO 3           /* after "</$MACRO" */
  40. #define MAST_TAG    8           /* inside a tag     */
  41. #define MAST_COMT   9           /* inside comment   */
  42. #define MAST_ERR   99           /* error occured    */
  43.  
  44. /*
  45.  *-------------------------------------
  46.  * handlers for opening/closing macro
  47.  *-------------------------------------
  48.  */
  49.  
  50. /*
  51.  * handle_macro
  52.  *
  53.  * handle for macro: add local attributes to global attributes,
  54.  * include macro text, remove local attributes
  55.  *
  56.  * params: open_mac..TRUE, if called by an opening macro
  57.  *         inpf......input file
  58.  */
  59. static BOOL handle_macro(HSCPRC * hp, HSCTAG * macro, BOOL open_mac)
  60. {
  61.     BOOL ok = FALSE;
  62.     EXPSTR *text;               /* macro text */
  63.     EXPSTR *fname;              /* pseudo-filename */
  64.     DLLIST *args;
  65.     ULONG mci = get_mci(hp);
  66.     INFILEPOS *fpos = NULL;
  67.  
  68.     /* determine filename & args */
  69.     args = macro->attr;
  70.     if (open_mac)
  71.     {
  72.         text = macro->op_text;
  73.         fpos = macro->start_fpos;
  74.     }
  75.     else
  76.     {
  77.         text = macro->cl_text;
  78.         fpos = macro->end_fpos;
  79.     }
  80.     fname = init_estr(0);
  81.  
  82.     if (fname)
  83.     {
  84.         /* debugging message */
  85.         DMC(
  86.                {
  87.                fprintf(stderr, DHL "--MACRO <");
  88.                if (!open_mac)
  89.                fprintf(stderr, "/");
  90.                fprintf(stderr, "%s> from %p\n", macro->name, text);
  91.                }
  92.         );
  93.  
  94.         /* create pseudo-filename */
  95.         ok = set_estr(fname, SPECIAL_FILE_ID "macro ");
  96.         if (!open_mac)
  97.             app_estrch(fname, '/');
  98.         ok &= app_estr(fname, macro->name);
  99.     }
  100.  
  101.     if (ok)
  102.     {
  103.         /* copy local vars to global list */
  104.         ok = copy_local_varlist(hp->defattr, args, mci);
  105.         DMC(prt_varlist(hp->defattr, "global attr (after copy_local_vars)"));
  106.     }
  107.  
  108.     if (ok)
  109.     {
  110.         /* include macro file */
  111.         ok = hsc_base_include_string(hp, estr2str(fname), estr2str(text),
  112.                                      IH_PARSE_MACRO, fpos);
  113.     }
  114.  
  115.     /* cleanup */
  116.     if (mci != MCI_ERROR)
  117.         remove_local_varlist(hp->defattr, mci);         /* remove local vars */
  118.     del_estr(fname);            /* release pseudo-filename */
  119.     unget_mci(hp);  /* restore scope */
  120.  
  121.     /* debugging message */
  122.     DMC(fprintf(stderr, DHL "--ENDMACRO <%s>\n", macro->name));
  123.  
  124.     return (FALSE);
  125. }
  126.  
  127. /*
  128.  * handle_op_macro
  129.  *
  130.  * handle for opening macro
  131.  */
  132. static BOOL handle_op_macro(HSCPRC * hp, HSCTAG * tag)
  133. {
  134.     return (handle_macro(hp, tag, TRUE));
  135. }
  136.  
  137. /*
  138.  * handle_cl_macro
  139.  *
  140.  * handle for closing macro
  141.  */
  142. static BOOL handle_cl_macro(HSCPRC * hp, HSCTAG * tag)
  143. {
  144.     return (handle_macro(hp, tag, FALSE));
  145. }
  146.  
  147. /*
  148.  *-------------------------------------
  149.  * macro creation functions
  150.  *-------------------------------------
  151.  */
  152.  
  153. /*
  154.  * read_macro_text
  155.  *
  156.  */
  157. static BOOL read_macro_text(HSCPRC * hp, HSCTAG * macro, BOOL open_mac)
  158. {
  159.     INFILE *inpf = hp->inpf;
  160.     BOOL ok = FALSE;
  161.     EXPSTR *macstr = NULL;
  162.     STRPTR nw = NULL;           /* word read from input */
  163.     BYTE state = MAST_TEXT;     /* current state */
  164.     LONG nesting = 0;
  165.  
  166.     /* skip first LF if any */
  167.     skip_next_lf(hp);
  168.  
  169.     /* init an EXPSTR for macro text,
  170.      * remember location of macro-def (for messages)
  171.      */
  172.     if (open_mac)
  173.     {
  174.         macro->op_text = init_estr(ES_STEP_MACRO);
  175.         macstr = macro->op_text;
  176.         macro->start_fpos = new_winfilepos(hp->inpf);
  177.     }
  178.     else
  179.     {
  180.         macro->cl_text = init_estr(ES_STEP_MACRO);
  181.         macstr = macro->cl_text;
  182.         macro->end_fpos = new_winfilepos(hp->inpf);
  183.     }
  184.  
  185.     /* reset rmt_str */
  186.     clr_estr(hp->rmt_str);      /* TODO: probably unneccessary; remove this */
  187.  
  188.     while (!((hp->fatal) || (state == MAST_CMACRO)))
  189.     {
  190.         /* read next word */
  191.         if (state == MAST_SLASH)
  192.             nw = infget_tagid(hp);
  193.         else if (state != MAST_TAG)
  194.             nw = infgetw(inpf);
  195.  
  196.         if (nw)
  197.         {
  198.             if (state == MAST_TAG)
  199.             {
  200.                 /*
  201.                  * skip inside tags
  202.                  */
  203.                 BYTE tag_state = TGST_TAG;      /* state var passe to */
  204.                 /*     eot_reached() */
  205.  
  206.                 do
  207.                 {
  208.                     if (eot_reached(hp, &tag_state))
  209.                         state = MAST_TEXT;
  210.  
  211.                     app_estr(macstr, infgetcws(inpf));
  212.                     app_estr(macstr, infgetcw(inpf));
  213.                 }
  214.                 while ((tag_state != TGST_END) && !(hp->fatal));
  215.             }
  216.             else
  217.             {
  218.                 switch (state)
  219.                 {
  220.                 case MAST_TEXT:
  221.                     if (!strcmp(nw, "<"))
  222.                         state = MAST_LT;
  223.                     break;
  224.  
  225.                 case MAST_LT:
  226.                     if (!strcmp(nw, "/"))
  227.                         state = MAST_SLASH;
  228.                     else if (!upstrcmp(nw, HSC_COMMENT_STR))
  229.                     {
  230.                         state = MAST_COMT;
  231.                     }
  232.                     else
  233.                     {
  234.                         /* handle "<$MACRO" (open macro) */
  235.                         if (!upstrcmp(nw, HSC_MACRO_STR))
  236.                             nesting++;  /* incr. macro nesting */
  237.                         state = MAST_TAG;
  238.                     }
  239.                     break;
  240.  
  241.                 case MAST_SLASH:
  242.                     if (!upstrcmp(nw, HSC_MACRO_STR))
  243.  
  244.                         /* handle "</$MACRO" (close macro) */
  245.                         if (nesting)
  246.                             nesting--;  /* decr. macro nesting */
  247.                         else
  248.                             state = MAST_CMACRO;        /* end of macro */
  249.                     else
  250.                         state = MAST_TAG;
  251.                     break;
  252.                 }
  253.  
  254.                 if (state == MAST_TEXT)
  255.                 {
  256.                     /* append current white spaces & word to macstr */
  257.                     app_estr(macstr, infgetcws(inpf));
  258.                     app_estr(macstr, infgetcw(inpf));
  259.                 }
  260.                 else if ((state == MAST_COMT)
  261.                          || (state == MAST_TAG))
  262.                 {
  263.                     /* append rmt_str to macstr, clear rmt_str,
  264.                      * append current word to macstr
  265.                      */
  266.                     app_estr(macstr, estr2str(hp->rmt_str));
  267.                     set_estr(hp->rmt_str, "");
  268.                     app_estr(macstr, infgetcws(inpf));
  269.                     app_estr(macstr, infgetcw(inpf));
  270.                 }
  271.                 else
  272.                 {
  273.                     /* append current white spaces & word to macstr */
  274.                     app_estr(hp->rmt_str, infgetcws(inpf));
  275.                     app_estr(hp->rmt_str, infgetcw(inpf));
  276.                 }
  277.  
  278.                 /*
  279.                  * skip hsc comment
  280.                  */
  281.                 if (state == MAST_COMT)
  282.                 {
  283.                     BYTE cstate = CMST_TEXT;    /* vars for eoc_reached() */
  284.                     LONG cnest = 0;
  285.                     BOOL end = FALSE;   /* end of comment reached? */
  286.  
  287.                     while (!end && !(hp->fatal))
  288.                     {
  289.                         end = eoc_reached(hp, &cstate, &cnest);
  290.                         app_estr(macstr, infgetcws(inpf));
  291.                         app_estr(macstr, infgetcw(inpf));
  292.                     }
  293.  
  294.                     state = MAST_TEXT;  /* reset state after comment */
  295.                 }
  296.             }
  297.         }
  298.         else
  299.         {
  300.             hsc_msg_eof(hp, "missing </" HSC_MACRO_STR ">");
  301.             state = MAST_ERR;
  302.         }
  303.     }                           /* while */
  304.  
  305.     /* check for legal end state */
  306.     if (state == MAST_CMACRO)
  307.     {
  308.         ok = parse_wd(hp, ">");
  309.     }
  310.  
  311.     /* if last char of macrotext is LF,
  312.      * replace it with a white space
  313.      */
  314.     if (ok)
  315.     {
  316.         STRPTR ms = estr2str(macstr);
  317.         size_t len = strlen(ms);
  318.  
  319.         /* TODO: würg! better call leftstr() here and strip last ch */
  320.         if (len && (ms[len - 1] == '\n'))
  321.             ms[len - 1] = '\0';
  322.  
  323.         DMC(fprintf(stderr, DHL "Macro text: \"%s\"\n", estr2str(macstr)));
  324.     }
  325.  
  326.     /* clear rmt_str */
  327.     clr_estr(hp->rmt_str);
  328.  
  329.     return (ok);
  330. }
  331.  
  332. /*
  333.  *-------------------------------------
  334.  * main handler function for creation
  335.  *-------------------------------------
  336.  */
  337.  
  338. /*
  339.  * handle_hsc_macro
  340.  *
  341.  * define a new macro tag
  342.  */
  343. BOOL handle_hsc_macro(HSCPRC * hp, HSCTAG * tag)
  344. {
  345.     BOOL ok = FALSE;
  346.     BOOL open_mac = FALSE;
  347.  
  348.     /* get name and argumets */
  349.     tag = def_tag_name(hp, &open_mac);
  350.     if (tag)
  351.     {
  352.         /* enable macro-flag */
  353.         tag->option |= HT_MACRO;
  354.         DDT(fprintf(stderr, DHL "def macro %s\n", tag->name));
  355.     }
  356.  
  357.     ok = (tag && def_tag_args(hp, tag));
  358.  
  359.     if (ok)
  360.     {
  361.         /* copy macro text to temp. file */
  362.         ok = read_macro_text(hp, tag, open_mac);
  363.         if (ok)
  364.         {
  365.             /* set tag handles & flags */
  366.             tag->option |= HT_NOCOPY;
  367.             tag->o_handle = handle_op_macro;
  368.             tag->c_handle = handle_cl_macro;
  369.         }
  370.     }
  371.  
  372.     return (FALSE);
  373. }
  374.  
  375.